<!DOCTYPE html>
<html lang="" xml:lang="">
  <head>
    <title>使用 BP 程序进行特定的光合测量</title>
    <meta charset="utf-8" />
    <meta name="author" content="祝介东" />
    <link rel="stylesheet" href="zh-CN.css" type="text/css" />
    <link rel="stylesheet" href="extra-rutgers.css" type="text/css" />
    <link rel="stylesheet" href="animate-min.css" type="text/css" />
  </head>
  <body>
    <textarea id="source">
class: center, middle, inverse, title-slide

# 使用 BP 程序进行特定的光合测量
## 以实际应用为例
### 祝介东
### 北京力高泰科技有限公司 技术部
### 2020-04-26 修改

---

background-image: url(https://s2.ax1x.com/2020/03/09/8S2l7T.png)

background-size: cover

class: left, middle, animated, fadeIn

# 主要内容

.pull-left[
# 1. 什么是 BP

# 2. STEP 的组成

# 3. STEP 组分介绍
]

.pull-right[
# 4. BP 已有的库

# 5. BP 界面介绍

# 6. BP 程序示例
]


---
class: animated, fadeIn, center, middle, inverse

# .large[BP 程序介绍]
---
class: animated, fadeIn

# 后台程序 (BP)

#### .tomato.large.bold[BP 的定义：]

BP（Background Program） 指的是一系列步骤的集合，能够在 6800 后台运行以完成各种任务。

#### .tomato.large.bold[什么是步骤（step）:]

本质上是 Python 中一个未经执行的字符串的表达式（expression），当其被调用时，表达式被 Python 的 `eval()` 或 `exec()` 执行。多数情况下，实际上被执行的是一个 .large.purple.bold[步骤 (STEP)] 的集合，以实现更复杂的目的，这个步骤的集合本质上是 Python 中的列表（list）。

也就是说 Background Program .large.purple.bold[本质上是 Python 程序]，而 LI-6800 就像是一台安装了 BSD 的电脑，来执行这些 BP。

---

class: animated, fadeIn, center, middle, inverse

# .large[BP 相关的知识]
---
class: animated, fadeIn

# 从 Python 的角度理解 BP

.tomato.bold[BP 可以无需 Python 基础使用，但了解相关的背景有助于加深对其理解和使用。]
- **list:** 列表，Python 中最万能的数据类型，写法是在 ** [] ** 内的，使用逗号分隔的值（values 或 items）。可以通过索引（index）来调用单个元素或多个元素，**Python 索引是以 0 为起始，也就是第一个元素应为 [0]**，它有个最大的特点就是值的类型不必相同,例如：

 ```python
list1 = ["LI-6800", 21, 0.08, "BP"]
 ```

- **STEP：**本质上是 list，Python 内并无此名词，是 BP 中 定义的一个由字符组成的列表，因为这个 list 的内容要被 `eval()` 或 `exec()` 执行，所以这些字符的写法要符合 bpdefs 模块的要求。例如列表中常见的几种赋值 ASSGIN 的写法为：

 ```python
steps = [ASSIGN("Fs", dd=DataDict('Flow_s','Status')),
ASSIGN("isOpen", exp="Fs &lt; 10"),
ASSIGN("tleafok",	exp="lambda t: 1 if (t != 0) and (t &gt; -20) and (t &lt; 60) else 0"),
ASSIGN("numTCs", exp="tleafok(data['Tleaf']) + tleafok(data['Tleaf2'])")
]
 ```
---
class: animated, fadeIn

# 从 Python 的角度理解 BP

- **eval:** STEP 中的内容是字符串，字符串是无法执行的，需要转为表达式（可以赋给变量的任意的对象），并且 eval 也只能接受单个表达式，并返回表达式的值。

- **exec：** 与 eval 类似，但不返回表达式的值，并能接受动态创建的语句或程序。在 BP 中，exec 实际由 EXEC 来替代。

.large.bold.purple[使用 BP 需要首先明白两点：]

1. 运行 BP 并不是直接运行 .py 文件，而是 .py 文件首先被编译（eval()）以获取 STEPS 列表，**然后 BP 使用这些 STEPS 作为数据来运行**。

2. 我们创建的变量是**存在于列表中**，变量和表达式在这一阶段必须**以字符的形式存在**。例如上一页中演示的 ASSIGN 第一个参数，实际应为一个变量（该阶段还不是），此时必须加引号将其作为字符存在（否则因为环境中无此变量，`eval() `就会报错）。换言之，我们写的代码必须发送到 eval() 或 exec() 两次：、
  1. 创建 STEP，也就是创建字符组成的 list，被 eval() 或 exec() 处理后变为 STEP 的数据，或者说是转变为表达式或语句的存在。
  
  2. BP 使用上面的 STEP 数据来构建 BP，然后作为 python 程序来运行。


???

exec is for statement and does not return anything. eval is for expression and returns value of expression.
expression means "something" while statement means "do something".

---
class: animated, fadeIn, center, middle, inverse

# .large[BP 与 AutoProgram 的差别]

---
class: animated, fadeIn
# BP 与 AutoProgram？

在 LI-6800 上内置了功能全面的 AutoProgram，为什么又有了 BP 呢，二者有什么不同？

### 二者差异主要体现在：

- BP 能实现所有的 AutoProgram，但 AutoProgram 对新手友好（无需编程，直接使用）。

- AutoProgram 每次只能执行一个，但理论上讲 BP 可以同时执行任何个数。

- BP 能够实现 AutoProgram 不能实现的功能，即可以在规则内定制自己所需要的程序。
---

class: animated, fadeIn, center, middle, inverse

# .large[STEP 介绍]
---
class: animated, fadeIn

# STEPS 的基本组成

## BP 的执行需要：

### 1. 编写 STEPS

### 2. STEPS 将被 eval() 或 exec()，生成一个参数化的 list 的过程

### 3. 系统安装的 python （使用 Python 3） 使用 BP 将 STEPS 作为数据运行的过程

.large.tomato[其中，我们需要做的工作仅仅是 STEPS 的编写过程。因此掌握 STEPS 的各个命令是写好 BP 的前提，我们先了解一下 BP 的命令。]
---
# 语句（statement）
&lt;iframe src="./statement.html" width=80% height=80% frameborder=0  allowtransparency="true"&gt; &lt;/iframe&gt;

---
# 流控制（program flow control）
&lt;iframe src="./flow-control.html" width=80% height=80% frameborder=0 allowtransparency="true"&gt; &lt;/iframe&gt;


---
class: animated, fadeIn, center, middle, inverse

# .large[STEP 已有的库（library）]

---
class: animated, fadeIn

# 已有的库

&lt;iframe src="./defines.html" width=80% height=80% frameborder=0 allowtransparency="true"&gt; &lt;/iframe&gt;

---
class: animated, fadeIn

# 已有的库

&lt;iframe src="./groups.html" width=80% height=80% frameborder=0 allowtransparency="true"&gt; &lt;/iframe&gt;

---
class: animated, fadeIn, center, middle, inverse

# .large[BP 使用界面（联机演示）]

---
class: inverse, center, middle, animated, fadeIn

# .large[谢谢！]

![](./img/gif-qrcode.gif)&lt;!-- --&gt;
## 关注公众号后获取更多精彩内容
    </textarea>
<style data-target="print-only">@media screen {.remark-slide-container{display:block;}.remark-slide-scaler{box-shadow:none;}}</style>
<script src="https://remarkjs.com/downloads/remark-latest.min.js"></script>
<script>var slideshow = remark.create({
"ratio": "16:9",
"highlightStyle": "ir-black",
"highlightLines": true,
"countIncrementalSlides": false
});
if (window.HTMLWidgets) slideshow.on('afterShowSlide', function (slide) {
  window.dispatchEvent(new Event('resize'));
});
(function(d) {
  var s = d.createElement("style"), r = d.querySelector(".remark-slide-scaler");
  if (!r) return;
  s.type = "text/css"; s.innerHTML = "@page {size: " + r.style.width + " " + r.style.height +"; }";
  d.head.appendChild(s);
})(document);

(function(d) {
  var el = d.getElementsByClassName("remark-slides-area");
  if (!el) return;
  var slide, slides = slideshow.getSlides(), els = el[0].children;
  for (var i = 1; i < slides.length; i++) {
    slide = slides[i];
    if (slide.properties.continued === "true" || slide.properties.count === "false") {
      els[i - 1].className += ' has-continuation';
    }
  }
  var s = d.createElement("style");
  s.type = "text/css"; s.innerHTML = "@media print { .has-continuation { display: none; } }";
  d.head.appendChild(s);
})(document);
// delete the temporary CSS (for displaying all slides initially) when the user
// starts to view slides
(function() {
  var deleted = false;
  slideshow.on('beforeShowSlide', function(slide) {
    if (deleted) return;
    var sheets = document.styleSheets, node;
    for (var i = 0; i < sheets.length; i++) {
      node = sheets[i].ownerNode;
      if (node.dataset["target"] !== "print-only") continue;
      node.parentNode.removeChild(node);
    }
    deleted = true;
  });
})();
(function() {
  "use strict"
  // Replace <script> tags in slides area to make them executable
  var scripts = document.querySelectorAll(
    '.remark-slides-area .remark-slide-container script'
  );
  if (!scripts.length) return;
  for (var i = 0; i < scripts.length; i++) {
    var s = document.createElement('script');
    var code = document.createTextNode(scripts[i].textContent);
    s.appendChild(code);
    var scriptAttrs = scripts[i].attributes;
    for (var j = 0; j < scriptAttrs.length; j++) {
      s.setAttribute(scriptAttrs[j].name, scriptAttrs[j].value);
    }
    scripts[i].parentElement.replaceChild(s, scripts[i]);
  }
})();
(function() {
  var links = document.getElementsByTagName('a');
  for (var i = 0; i < links.length; i++) {
    if (/^(https?:)?\/\//.test(links[i].getAttribute('href'))) {
      links[i].target = '_blank';
    }
  }
})();
// adds .remark-code-has-line-highlighted class to <pre> parent elements
// of code chunks containing highlighted lines with class .remark-code-line-highlighted
(function(d) {
  const hlines = d.querySelectorAll('.remark-code-line-highlighted');
  const preParents = [];
  const findPreParent = function(line, p = 0) {
    if (p > 1) return null; // traverse up no further than grandparent
    const el = line.parentElement;
    return el.tagName === "PRE" ? el : findPreParent(el, ++p);
  };

  for (let line of hlines) {
    let pre = findPreParent(line);
    if (pre && !preParents.includes(pre)) preParents.push(pre);
  }
  preParents.forEach(p => p.classList.add("remark-code-has-line-highlighted"));
})(document);</script>

<script>
slideshow._releaseMath = function(el) {
  var i, text, code, codes = el.getElementsByTagName('code');
  for (i = 0; i < codes.length;) {
    code = codes[i];
    if (code.parentNode.tagName !== 'PRE' && code.childElementCount === 0) {
      text = code.textContent;
      if (/^\\\((.|\s)+\\\)$/.test(text) || /^\\\[(.|\s)+\\\]$/.test(text) ||
          /^\$\$(.|\s)+\$\$$/.test(text) ||
          /^\\begin\{([^}]+)\}(.|\s)+\\end\{[^}]+\}$/.test(text)) {
        code.outerHTML = code.innerHTML;  // remove <code></code>
        continue;
      }
    }
    i++;
  }
};
slideshow._releaseMath(document);
</script>
<!-- dynamically load mathjax for compatibility with self-contained -->
<script>
(function () {
  var script = document.createElement('script');
  script.type = 'text/javascript';
  script.src  = 'https://mathjax.rstudio.com/latest/MathJax.js?config=TeX-MML-AM_CHTML';
  if (location.protocol !== 'file:' && /^https?:/.test(script.src))
    script.src  = script.src.replace(/^https?:/, '');
  document.getElementsByTagName('head')[0].appendChild(script);
})();
</script>
  </body>
</html>
